﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace iTool.ClusterComponent
{
    public class ConnectionStatisticsService : iToolServiceBase, IConnectionStatisticsService
    {
        /// <summary>
        /// 客户端类型
        /// browser/app/小程序
        /// </summary>
        private ConcurrentDictionary<string, long> ClientTypes { get; set; }
        /// <summary>
        /// 客户端环境
        /// ios/安卓/...
        /// </summary>
        private ConcurrentDictionary<string, long> PlatformTypes { get; set; }

        /// <summary>
        /// 客户端位置-省
        /// </summary>
        private ConcurrentDictionary<string, long> ProvinceTypes { get; set; }


        /// <summary>
        /// 日活客户端
        /// uuid
        /// </summary>
        private ConcurrentDictionary<string, bool> DayOnlineUUIDs { get; set; }


        public ConnectionStatisticsService()
        {
            //this.OnlineUsers = new ConcurrentDictionary<string, long>();
            this.ClientTypes = new ConcurrentDictionary<string, long>();
            this.PlatformTypes = new ConcurrentDictionary<string, long>();
            this.ProvinceTypes = new ConcurrentDictionary<string, long>();
            this.DayOnlineUUIDs = new ConcurrentDictionary<string, bool>();
        }

        public override Task OnActivateAsync()
        {
            DateTime.TryParse(DateTime.Now.AddDays(1).ToString("d"), out DateTime firstRunTime);

            base.RegisterTimer(x => this.EveryDayTask(), null, firstRunTime - DateTime.Now, TimeSpan.FromDays(1));

            return base.OnActivateAsync();
        }

        public Task Disconnect(string server, ConnectorInfo clientInfo)
        {
            //if (this.OnlineUsers.ContainsKey(server))
            //    this.OnlineUsers[server] -= 1;

            if (this.DayOnlineUUIDs.ContainsKey(clientInfo.UUID))
            {
                this.DayOnlineUUIDs[clientInfo.UUID] = false;
            }

            // 计算客户端类型
            clientInfo.Type = string.IsNullOrWhiteSpace(clientInfo.Type) ? "none" : clientInfo.Type;
            if (this.ClientTypes.ContainsKey(clientInfo.Type))
                this.ClientTypes[clientInfo.Type] -= 1;

            // 计算客户端环境
            clientInfo.Platform = string.IsNullOrWhiteSpace(clientInfo.Platform) ? "none" : clientInfo.Platform;
            if (this.PlatformTypes.ContainsKey(clientInfo.Platform))
                this.PlatformTypes[clientInfo.Platform] -= 1;

            // 计算客户端位置
            clientInfo.Province = string.IsNullOrWhiteSpace(clientInfo.Province) ? "none" : clientInfo.Province;
            if (this.ProvinceTypes.ContainsKey(clientInfo.Province))
                this.ProvinceTypes[clientInfo.Province] -= 1;

            return Task.CompletedTask;
        }

        public Task Connection(string server, ConnectorInfo clientInfo)
        {
            base.PlanDispose(delayTimeSpan: TimeSpan.FromDays(1));

            // 在线用户计数器
            //if (this.OnlineUsers.ContainsKey(server))
            //    this.OnlineUsers[server]++;
            //else
            //    this.OnlineUsers.TryAdd(server, 1);

            // 日活用户
            if (this.DayOnlineUUIDs.ContainsKey(clientInfo.UUID))
            {
                this.DayOnlineUUIDs[clientInfo.UUID] = true;
            }
            else
            {
                this.DayOnlineUUIDs.TryAdd(clientInfo.UUID, true);
            }
            // 计算客户端类型
            clientInfo.Type = string.IsNullOrWhiteSpace(clientInfo.Type) ? "none" : clientInfo.Type;
            if (this.ClientTypes.ContainsKey(clientInfo.Type))
                this.ClientTypes[clientInfo.Type] += 1;
            else
                this.ClientTypes.TryAdd(clientInfo.Type, 1);

            // 计算客户端环境
            clientInfo.Platform = string.IsNullOrWhiteSpace(clientInfo.Platform) ? "none" : clientInfo.Platform;
            if (this.PlatformTypes.ContainsKey(clientInfo.Platform))
                this.PlatformTypes[clientInfo.Platform] += 1;
            else
                this.PlatformTypes.TryAdd(clientInfo.Platform, 1);

            // 计算客户端位置
            clientInfo.Province = string.IsNullOrWhiteSpace(clientInfo.Province) ? "none" : $"{clientInfo.Province}";
            clientInfo.Province = clientInfo.Province.ToString();
            if (this.ProvinceTypes.ContainsKey(clientInfo.Province))
                this.ProvinceTypes[clientInfo.Province] += 1;
            else
                this.ProvinceTypes.TryAdd(clientInfo.Province, 1);

            return Task.CompletedTask;
        }

        public Task<ConcurrentDictionary<string, long>> GetNoderConnectCount()
        {
            ConcurrentDictionary<string, long> result = new ConcurrentDictionary<string, long>();
            result.TryAdd("All", this.DayOnlineUUIDs.Where(item => item.Value).Count());
            return Task.FromResult(result);
        }




        public Task<long> GetSumCount()
        {
            return Task.FromResult<long>(this.DayOnlineUUIDs.Where(item => item.Value).Count());
        }

        public Task<long> GetDayActiveCount()
        {
            return Task.FromResult(this.DayOnlineUUIDs.LongCount());
        }

        //public Task<long> GetConnectCountByServer(string server)
        //{
        //    if (this.OnlineUsers.TryGetValue(server, out long count))
        //    {
        //        return Task.FromResult(count);
        //    }
        //    else
        //    {
        //        return Task.FromResult<long>(default);
        //    }
        //}

        private Task EveryDayTask()
        {
            this.DayOnlineUUIDs = new ConcurrentDictionary<string, bool>();
            return Task.CompletedTask;
        }

        //public Task<long> GetSumCount(string server)
        //{
        //    if (this.OnlineUsers.ContainsKey(server))
        //    {
        //        return Task.FromResult(this.OnlineUsers[server]);
        //    }
        //    return Task.FromResult<long>(0);
        //}

        public Task<StatisticsResult> GetStatisticsAsync()
        {
            var result = new StatisticsResult();
            result.OnlineCount = this.DayOnlineUUIDs.Where(item => item.Value).Count();
            result.DayOnlineCount = this.DayOnlineUUIDs.LongCount();
            result.ClientTypes = this.ClientTypes.ToDictionary(item => item.Key, item => item.Value);
            result.PlatformTypes = this.PlatformTypes.ToDictionary(item => item.Key, item => item.Value);
            result.ProvinceTypes = this.ProvinceTypes.ToDictionary(item => item.Key, item => item.Value);
            return Task.FromResult(result);
        }
    }
}
